<?php
/**
 * 支付回调
 * User: 梁晓伟  lxw11109@gmail.com
 * Date: 2017-09-09
 * Time: 15:33
 */

namespace App\Http\Controllers\Api\V1\Manager\Mall;


use App\Http\Controllers\Controller;
use App\Libs\Contracts\PayMent\AliPay\Web\pagepay\service\AlipayTradeService;
use App\Libs\Contracts\PayMent\Wxpay\WxPayApi;
use App\Libs\httpUtil;
use App\Models\Activity;
use App\Models\ActivityOrder;
use App\Models\ActivityOrderDetail;
use App\Models\BalanceLog;
use App\Models\ContractorCourse;
use App\Models\Course;
use App\Models\CourseOrder;
use App\Models\CourseOrderDetail;
use App\Models\GiftCommodity;
use App\Models\GiftOrder;
use App\Models\GiftOrderDetail;
use App\Models\HealthExamination;
use App\Models\Order;
use App\Models\PaymentCallback;
use App\Models\RechargeOrder;
use App\Models\User;
use App\Models\UserRecharge;
use App\Services\Front\AreaTotalService;
use App\Services\Front\CourseService;
use App\Services\Front\QrcodeService;
use App\Services\Front\UserScoreService;
use App\Services\Front\UserService;
use App\Services\Wx\AliService;
use Illuminate\Http\Request;

class PayCallbackController extends Controller
{
    /**
     * 微信回调
     * @param Request $request
     * @return string
     */
    public function wxCallback(Request $request)
    {
        $xmldata = file_get_contents("php://input");
        \Log::info("PayCallbackController wxCallback11" . $xmldata);
        $result = xmlToArray($xmldata);
        $orderNo = $result['out_trade_no'];

        $wxPayApi = new WxPayApi();
        $sign = $wxPayApi->MakeSign($result);
        \Log::info("PayCallbackController wxCallback" . $xmldata);

      //  if ($sign === $result['sign'])
        {//验证签名
            \Log::info("PayCallbackController wxCallback1" . $result['sign']);
            \Log::info("PayCallbackController wxCallback2" .$sign);
            try {
                \DB::beginTransaction();
                $order = Order::select()->where('orderNo', $orderNo)->lockForUpdate()->first();
                if (!$order) {
                    throw new \Exception("订单不存在");
                }
                if ($order['totalPrice'] < 0) {
                    throw new \Exception("订单金额错误" . $order['totalPrice']);
                }

                if ($order['totalPrice'] == $result['total_fee']) {
                    $status = Order::where(['orderNo' => $orderNo, 'orderStatus' => 'NONPAYMENT'])->update(['orderStatus' => 'ORDERFINISH', 'payTime' => date('Y-m-d H:i:s')]);
                    if (!$status) {
                        throw new \Exception("修改订单状态失败");
                    }
                    $courseService = new CourseService();
                    $status = $courseService->callback($orderNo);
                    if (!$status) {
                        throw new \Exception("分佣失败");
                    }
                    \DB::commit();
                    return "<xml>
                            <return_code><![CDATA[SUCCESS]]></return_code>
                            <return_msg><![CDATA]></return_msg>
                        </xml>";
                } else {
                    throw new \Exception("订单金额不一致");
                }
            } catch (\Exception $e) {
                \DB::rollback();
                \Log::error("PayCallbackController wxCallback" . $e->getMessage());
            }
        }
    }

    /**
     * 支付宝回调
     * @param Request $request
     */
    public function aliCallback(Request $request)
    {
       // $config = getAliConfig();
        $arr = $_POST;
//        $alipaySevice = new AlipayTradeService($config);
//        $result = $alipaySevice->check($arr);
        /* 实际验证过程建议商户添加以下校验。
           1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
            2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
            3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
            4、验证app_id是否为该商户本身。
        */
        $result = true;
        $orderNo = $arr['out_trade_no'];//商户订单号
        $totalAmount = $arr['total_amount'] * 100; //订单金额
        $appId = $arr['app_id'];
        $trade_status = $_POST['trade_status']; //交易状态
        if ($result) {//验证成功
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //请在这里加上商户的业务逻辑程序代
            try {
                \DB::beginTransaction();
                if ($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {

                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                    //如果有做过处理，不执行商户的业务程序

                    $order = Order::select()->where('orderNo', $orderNo)->lockForUpdate()->first();
                    if (!$order) {
                        throw new \Exception("订单不存在");
                    }
                    if ($order['totalPrice'] < 0) {
                        throw new \Exception("订单金额错误" . $order['totalPrice']);
                    }

                        $status = Order::where(['orderNo' => $orderNo, 'orderStatus' => 'NONPAYMENT'])->update(['orderStatus' => 'ORDERFINISH', 'payTime' => date('Y-m-d H:i:s')]);
                        if (!$status) {
                            throw new \Exception("修改订单状态失败");
                        }
                        $courseService = new CourseService();
                        $status = $courseService->callback($orderNo);
                        if (!$status) {
                            throw new \Exception("分佣失败");
                        }
                    \DB::commit();
                }
                echo "success";        //请不要修改或删除
            } catch (\Exception $e) {
                \DB::rollback();
                \Log::error($orderNo);

                \Log::error("PayCallbackController aliCallback  " . $e->getMessage());
            }
        } else {
            //验证失败
            echo "fail";    //请不要修改或删除

        }
    }

    /**
     * 支付宝回调
     * @param Request $request
     */
    public function aliRechargeCallback(Request $request)
    {
        // $config = getAliConfig();
        $arr = $_POST;
//        $alipaySevice = new AlipayTradeService($config);
//        $result = $alipaySevice->check($arr);
        /* 实际验证过程建议商户添加以下校验。
           1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
            2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
            3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
            4、验证app_id是否为该商户本身。
        */
        $result = true;
        $orderNo = $arr['out_trade_no'];//商户订单号
        $totalAmount = $arr['total_amount'] * 100; //订单金额
        $appId = $arr['app_id'];
        $trade_status = $_POST['trade_status']; //交易状态
        if ($result) {//验证成功
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //请在这里加上商户的业务逻辑程序代
            try {
                \DB::beginTransaction();
                if ($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {

                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                    //如果有做过处理，不执行商户的业务程序


                    $userRecharges = RechargeOrder::where('rechargeOrderNo',$orderNo)->lockForUpdate()->get()->toArray();
                    if (!$userRecharges) {
                        throw new \Exception("订单不存在");
                    }

                    foreach ($userRecharges as $userRecharge){
                        if ($userRecharge['status'] != 1){
                            $data['payTime'] = date('Y-m-d H:i:s', time());
                            $data['status'] = 1;

                            $balance = $userRecharge['changePrice'];
                            $user = User::find($userRecharge['userId']);
                            User::where('userId', $userRecharge['userId'])->increment('balance', $balance);
                            RechargeOrder::where('rechargeOrderNo',$orderNo)->update($data);
                            BalanceLog::create([
                                "balanceLogType"=>'RECHARGE',
                                "balance"=>$user['balance']+$balance,
                                "changePrice"=>$balance,
                                "createTime"=>date("Y-m-d H:i:s"),
                                "rechargeType"=>"WX",
                                "userId"=>$userRecharge['userId'],
                                "orderNo"=>$userRecharge['rechargeOrderNo'],
                                "callpack"=>json_encode($result),
                            ]);
                        }
                    }
                    \DB::commit();
                }
                echo "success";        //请不要修改或删除
            } catch (\Exception $e) {
                \DB::rollback();
                \Log::error($orderNo);

                \Log::error("PayCallbackController aliCallback  " . $e->getMessage());
            }
        } else {
            //验证失败
            echo "fail";    //请不要修改或删除

        }
    }
    public function callbackRecharge()
    {
        $postXml = file_get_contents("php://input"); //接收微信参数

        $result = xmlToArray($postXml);

        \Log::info($result);
        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            \DB::beginTransaction();
            $out_trade_no = $result['out_trade_no'];
            $userRecharges = RechargeOrder::where('rechargeOrderNo',$out_trade_no)->lockForUpdate()->get()->toArray();
            foreach ($userRecharges as $userRecharge){
                if ($userRecharge['status'] != 1){
                    $data['payTime'] = date('Y-m-d H:i:s', time());
                    $data['status'] = 1;

                    $balance = $userRecharge['changePrice'];
                    $user = User::find($userRecharge['userId']);
                    User::where('userId', $userRecharge['userId'])->increment('balance', $balance);
                    RechargeOrder::where('rechargeOrderNo',$out_trade_no)->update($data);
                    BalanceLog::create([
                        "balanceLogType"=>'RECHARGE',
                        "balance"=>$user['balance']+$balance,
                        "changePrice"=>$balance,
                        "createTime"=>date("Y-m-d H:i:s"),
                        "rechargeType"=>"WX",
                        "userId"=>$userRecharge['userId'],
                        "orderNo"=>$userRecharge['rechargeOrderNo'],
                        "callpack"=>json_encode($result),
                    ]);
                }
            }

            \DB::commit();
        }
        echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    }


    /**
     * @title 验证支付票据 完成订单接口
     */
public function verifyReceipt(Request $request)
{

    $receipt = $request->receipt;  //票据
    $orderSn = $request->orderNo;  //订单号


   //判断订单是否存在 检查状态

    //写入日志  查看票据格式  记录日志的方法 这个方法不贴出来了
   //\Log::info('request-param',json_encode(['receipt'=>$receipt,'orderSn'=>$orderSn]));

   //password 是验证秘钥
   $jsonItem = json_encode(['receipt-data'=>$receipt]);


   $url= 'https://buy.itunes.apple.com/verifyReceipt';      //正式



    $h = new httpUtil();
   //模拟post提交   下面会贴出来
   $result = $h->http_post($url,$jsonItem);
   $result = json_decode($result,true);
    if ($result['status'] == 21007 ){
        $url= 'https://sandbox.itunes.apple.com/verifyReceipt';  //测试
        $result = $h->http_post($url,$jsonItem);
        $result = json_decode($result,true);
    }
   if($result['status'] !== 0){
       //验证失败 返回app错误状态
       $d['payStatus'] = false;

       return $this->apiResponse($d);
   }

    $out_trade_no = $orderSn;
    $userRecharges = RechargeOrder::where('rechargeOrderNo',$out_trade_no)->lockForUpdate()->get()->toArray();
    foreach ($userRecharges as $userRecharge){
        if ($userRecharge['status'] != 1){
            $data['payTime'] = date('Y-m-d H:i:s', time());
            $data['status'] = 1;

            $balance = $userRecharge['changePrice'];
            $user = User::find($userRecharge['userId']);
            User::where('userId', $userRecharge['userId'])->increment('balance', $balance);
            RechargeOrder::where('rechargeOrderNo',$out_trade_no)->update($data);
            BalanceLog::create([
                "balanceLogType"=>'RECHARGE',
                "balance"=>$user['balance']+$balance,
                "changePrice"=>$balance,
                "createTime"=>date("Y-m-d H:i:s"),
                "rechargeType"=>"WX",
                "userId"=>$userRecharge['userId'],
                "orderNo"=>$userRecharge['rechargeOrderNo'],
                "callpack"=>json_encode($result),
            ]);
        }
    }
//   $d['data'] = $result['receipt']['in_app'];
   $d['payStatus'] = true;
   return $this->apiResponse($d);
//   //验证完成加入日志
//    \Log::info('verifyReceipt_finish',json_encode($result));
//
//   //找出时间最大的数组
//   $receiptitem = $result['latest_receipt_info'];
//
//   //这个是排序的方法  下面回帖出来 苹果会把这个会员往期的订单信息全部返回，需要找出来最近的那一组信息
//   $item = $this->arraySort($receiptitem,'purchase_date','desc');
//
//   //判断一下过期时间 延长会员时间
//
//   $orderThird = $item['transaction_id'];                //本次订阅的订单号
//
//   $orderThirdFirst = $item['original_transaction_id'];  //这个是原始订单号
//
//   if($orderThird == $orderThirdFirst){                  //首次订阅 两个相等
//
//   }else{
//
//       //判断过期时间和当前时间比较   expires_date_ms是毫秒单位
//
//       if($item['expires_date_ms']/1000 > time()){
//
//       }else{
//           //过期处理  票据失效
//       }
//   }

  //接下来处理订单业务逻辑，处理订单，修改订单信息，original_transaction_id 把这个单号和存入订单信息， 在异步回调的时候根据这个单号来查找订单信息来判断是哪个用户，苹果票据里面也有产品product_id，是app_store的产品id,不是自己业务的产品id，可以在后台把自己的产品ID和 product_id 关联,处理业务逻辑。

}
//查找最新数据的方法
    public static function arraySort($arr,$key,$type='asc'){

        $keyArr = []; // 初始化存放数组将要排序的字段值
        foreach ($arr as $k=>$v){
            $keyArr[$k] = $v[$key]; // 循环获取到将要排序的字段值
        }
        if($type == 'asc'){
            asort($keyArr); // 排序方式,将一维数组进行相应排序
        }else{
            arsort($keyArr);
        }
        foreach ($keyArr as $k=>$v){
            $newArray[$k] = $arr[$k]; // 循环将配置的值放入响应的下标下
        }
        $newArray = array_merge($newArray); // 重置下标
        return $newArray[0]; // 数据返回
    }

}